/**
 * @projectName: pet-joy-home
 * @author: 小飞
 * @description: TODO
 * @date: 2024/8/13 13:26
 * @version: 1.0
 */
package com.home.aspect;

import com.home.annotaion.AutoFill;
import com.home.constant.MessageConstant;
import com.home.enumCode.OperationType;
import com.home.exception.BaseException;
import com.home.utils.SecurityContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;

@Component
@Aspect
@Slf4j
public class AutoFillAspect {

    /**
     * 切入点
     */
    @Pointcut("execution(* com.home.mapper.*.*(..)) && @annotation(com.home.annotaion.AutoFill)")
    public void autoFillPointCut() {

    }

    /**
     * 为公共字段赋值
     *
     * @param joinPoint
     */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint) {
        // 1.获取当前被拦截方法上的数据库操作类型,为什么要强转，因为要获取方法上的注解
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); // 获取签名对象
        AutoFill autoFill = methodSignature.getMethod().getAnnotation(AutoFill.class); //得到这个注解的对象
        OperationType value = autoFill.value(); // 得到注解里面的内容看看是属于什么方法

        // 2.获取到我们被拦截的犯法参数-- 实体对象
        Object[] args = joinPoint.getArgs();
        //获取到实体对象
        Object entity = args[0];
        Long employeeId = SecurityContextUtil.getLoginUser().getUser().getId();
        if (OperationType.INSERT.equals(value)) {
            try {
                //根据方法赋值
                Method createTime = entity.getClass().getDeclaredMethod(MessageConstant.SET_CREATE_TIME, Date.class);
                Method updateTime = entity.getClass().getDeclaredMethod(MessageConstant.SET_UPDATE_TIME, Date.class);
                Method createUser = entity.getClass().getDeclaredMethod(MessageConstant.SET_CREATE_USER, Long.class);
                Method updateUser = entity.getClass().getDeclaredMethod(MessageConstant.Set_UPDATE_USER, Long.class);
                //通过反射赋值
                createTime.invoke(entity, new Date());
                createUser.invoke(entity, employeeId);
                updateTime.invoke(entity, new Date());
                updateUser.invoke(entity, employeeId);
            } catch (Exception e) {
                throw new BaseException(e.getMessage());
            }
        } else if (OperationType.UPDATE.equals(value) || OperationType.DELETE.equals(value)) {
            try {
                Method updateTime = entity.getClass().getDeclaredMethod(MessageConstant.SET_UPDATE_TIME, Date.class);
                Method updateUser = entity.getClass().getDeclaredMethod(MessageConstant.Set_UPDATE_USER, Long.class);
                updateTime.invoke(entity, new Date());
                updateUser.invoke(entity, employeeId);
            } catch (Exception e) {
                throw new BaseException(e.getMessage());
            }
        }
    }

    /**
     * 得到service中方法的执行时间
     *
     * @param proceedingJoinPoint
     * @return
     */
    @Around("execution(* com.home.service.*.*(..))")
    public Object getRunTime(ProceedingJoinPoint proceedingJoinPoint) {
        //MethodSignature为什么上面要使用这个呢，这个是Signature的子类提供了更多相关操作的方法
        Signature signature = proceedingJoinPoint.getSignature();
        try {
            long start = System.currentTimeMillis();
            Object proceed = proceedingJoinPoint.proceed();
            long end = System.currentTimeMillis();
            double useTime = (end - start)/1000.00;
            log.info("{}方法被调用,所耗时间为:{}秒",signature,useTime);
            return proceed;
        } catch (Throwable e) {
            throw new BaseException(e.getMessage());
        }
    }
}
